package cn.tedu.charging.device.repository;

import cn.tedu.charging.common.consts.RedisConstants;
import cn.tedu.charging.common.vo.StationInfoVO;
import cn.tedu.charging.device.mapper.StationMapper;
import cn.tedu.charging.device.po.StationPO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.*;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.GeoOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Repository;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.stream.Collectors;

//仓储层 操作数据分层
@Repository
@Slf4j
public class StationRepository {
    //操作持久层
    @Autowired
    private StationMapper stationMapper;
    //操作缓存
    @Autowired
    private RedisTemplate redisTemplate;

    public List<StationInfoVO> nearStations(Double longitude, Double latitude, Double distance) {
        //操作geo客户端
        GeoOperations<String,Integer> opsForGeo = redisTemplate.opsForGeo();
        //操作string客户端
        ValueOperations<String, StationPO> opsForValue = redisTemplate.opsForValue();
        //读取redis附近充电站逻辑 先查询geo radius 循环元素 使用id 获取string缓存 拼接stationName
        //georadius WITHCOORD WITHDIST
        //1.封装一个查询条件 Circle圆 中心点 半径
        Circle circle=assembleCircle(longitude,latitude,distance);
        //2.除了查询范围内的元素 memebr 携带元素地理位置 元素和中心点距离
        RedisGeoCommands.GeoRadiusCommandArgs args=
                RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs().includeCoordinates().includeDistance();
        GeoResults<RedisGeoCommands.GeoLocation<Integer>> stations = opsForGeo.radius(RedisConstants.STATIONS_GEO, circle, args);
        //3.从stations中 获取集合数据
        List<GeoResult<RedisGeoCommands.GeoLocation<Integer>>> contents = stations.getContent();
        List<StationInfoVO> vos=null;
        if (contents!=null && contents.size()>0){
            vos=contents.stream().map(geoResult->{
                StationInfoVO vo=new StationInfoVO();
                vo.setId(geoResult.getContent().getName());
                vo.setStationLat(new BigDecimal(geoResult.getContent().getPoint().getY()));
                vo.setStationLng(new BigDecimal(geoResult.getContent().getPoint().getX()));
                vo.setDistance(geoResult.getDistance().getValue());//只取小数点2位
                double voDis = geoResult.getDistance().getValue();
                //从米的单位 编程km
                vo.setDistance(new BigDecimal(voDis).divide(new BigDecimal(1000)).setScale(2, RoundingMode.HALF_UP).doubleValue());
                Integer stationId = geoResult.getContent().getName();
                StationPO stationPO = opsForValue.get(RedisConstants.STATION_STRING_PREFIX + stationId);
                vo.setStationName(stationPO.getStationName());
                return vo;
            }).collect(Collectors.toList());
        }
        return vos;
    }

    private Circle assembleCircle(Double longitude, Double latitude, Double distance) {
        Point center=new Point(longitude,latitude);
        //distance
        Distance radius=new Distance(distance);
        return new Circle(center,radius);
    }

    public StationPO getStationById(Integer id) {
        //缓存 数据结构是 key-value string类型
        ValueOperations<String,StationPO> opsForValue = redisTemplate.opsForValue();
        String stationKey=RedisConstants.STATION_STRING_PREFIX+id;
        StationPO stationPO = opsForValue.get(stationKey);
        if (stationPO==null){
            log.info("当前站场:{},不在缓存中",id);
            //缓存未命中 查询数据库
            stationPO = stationMapper.selectById(id);
            //存储到缓存一份
            opsForValue.set(stationKey,stationPO);
        }
        //stationPO应该是有值的
        return stationPO;
    }
}
